#ifndef __DIR_PROTO_H__
#define __DIR_PROTO_H__

#include "table_proto.h"
#include "../chunk/chunk_proto.h"
#include "chunk.h"
#include "fileinfo.h"
#include "fs_proto.h"
#include "volume_proto.h"
#include "cluster.h"
#include "lease.h"


static inline void pool_proto_layout_check()
{
        YASSERT((DIR_PROTO_MAP_AREA + DIR_PROTO_INFO_AREA + DIR_PROTO_EXTERN_AREA) % PAGE_SIZE == 0);

        YASSERT((DIR_PROTO_MAP_AREA + DIR_PROTO_INFO_AREA + DIR_PROTO_EXTERN_AREA)
                + (DIR_PROTO_REC_COUNT * DIR_PROTO_REC_SIZE) < LICH_CHUNK_SPLIT);

        YASSERT((DIR_PROTO_EXTERN_COUNT * 512) < DIR_PROTO_EXTERN_AREA);

        YASSERT(DIR_PROTO_REC_COUNT / CHAR_BIT < DIR_PROTO_MAP_AREA);
}

typedef struct {
        uint32_t loc;
        uint32_t idx;
} loc_t;

typedef struct {
        loc_t loc;
        char *name;
        chkinfo_t *chkinfo;
} pool_proto_entry_t;

typedef struct __pool_proto {
        fileid_t chkid; //must be the first
        nid_t parentnid;
        fileid_t parentid;
        uint64_t count;
        uint32_t magic;
        table_proto_t *table_proto;

        int table_count;
        table_proto_t **table_array;

        fileinfo_t fileinfo;
        time_t ltime;
        time_t uptime;

        lease_t lease;

        uint64_t info_version;

        int name_locked; //name table lock;
        hashtable_t name_tab;
        hashtable_t id_tab;
        char pool[MAX_NAME_LEN];

        int (*setattr)(struct __pool_proto *, fileinfo_t *fileinfo, const setattr_t *setattr);
        int (*getattr)(struct __pool_proto *, fileinfo_t *fileinfo);

        int (*needreload)(struct __pool_proto *);
        int (*lookup)(struct __pool_proto *, const char *name, chkinfo_t *chkinfo);

        int (*mkpool)(struct __pool_proto *, const chkid_t *parent,
                     const char *name, const char *site_name, const setattr_t *setattr, chkinfo_t *chkinfo);
        int (*rmpool)(struct __pool_proto *, const char *name);
        int (*listpool_open)(struct __pool_proto *, int fd);

        int (*mkvol)(struct __pool_proto *, const chkid_t *parent,
                      const char *name, const char *site_name, const setattr_t *setattr, chkinfo_t *chkinfo);
        int (*mkvolwith)(struct __pool_proto *, const chkid_t *parent,
                      const char *name, const chkinfo_t *chkinfo);
        int (*unlink)(struct __pool_proto *, const char *name, int force);

        int (*cleanup)(struct __pool_proto *, const char *name);
        int (*newtab)(struct __pool_proto *, table_proto_t **_table_proto);

        int (*rename)(struct __pool_proto *pool_proto, const fileid_t *from, const char *fromname,
                      const fileid_t *to, const char *toname);
        int (*rename_lock)(struct __pool_proto *pool_proto, const fileid_t *src, const char *name, int force);
        int (*rename_unlock)(struct __pool_proto *pool_proto, const chkinfo_t *chkinfo);

        int (*xattr_set)(struct __pool_proto *pool_proto, const char *key, const char *value,
                        uint32_t valuelen, int flag);
        int (*xattr_get)(struct __pool_proto *pool_proto, const char *key, char *value, int *valuelen);
        int (*xattr_list)(struct __pool_proto *pool_proto, char *buf, int *buflen);
        int (*xattr_remove)(struct __pool_proto *pool_proto, const char *key);

        int (*chunk_sync)(struct __pool_proto *, const chkid_t *chkid);
        int (*chunk_reject)(struct __pool_proto *, const chkid_t *chkid, const nid_t *bad, chkinfo_t *chkinfo);
        int (*chunk_set)(struct __pool_proto *, const chkid_t *chkid, const nid_t *nid, int status);
        int (*chunk_check)(struct __pool_proto *pool_proto, const chkid_t *);
        int (*chunk_update)(struct __pool_proto *pool_proto, const chkinfo_t *chkinfo, const nid_t *owner, uint64_t info_version);
        int (*chunk_move)(struct __pool_proto *pool_proto, const chkid_t *chkid, const nid_t *dist, int dist_count);
        int (*chunk_cleanup)(struct __pool_proto *pool_proto, const chkid_t *chkid,
                             const nid_t *nid, uint64_t meta_version);
        int (*chunk_getinfo)(struct __pool_proto *, const chkid_t *chkid, chkinfo_t *chkinfo);
        int (*chunk_iterator)(struct __pool_proto *, func2_t func2, void *_arg);
} pool_proto_t;

int pool_proto_load(pool_proto_t **_pool_proto, const char *pool, const chkid_t *parent, const chkinfo_t *chkinfo);
void pool_proto_destroy(pool_proto_t *pool_proto);

int pool_proto_update(pool_proto_t *pool_proto,
                          const char *key, const chkinfo_t *chkinfo, const loc_t *loc);

int pool_proto_insert(pool_proto_t *pool_proto, const char *name,
                     const chkinfo_t *chkinfo);
int pool_proto_del(pool_proto_t *pool_proto, const char *key);
int pool_proto_renew(pool_proto_t *pool_proto);

#endif
